#include <cxxomfort/cxxomfort.hpp>
#include <cxxomfort/cstdint.hpp> // integer types
#include <cxxomfort/library/type_name.hpp>
#include <iostream>
#include "../library/literals.hpp"
#include "../library/affixes/integer.hpp"

// reference: 
// https://en.cppreference.com/w/cpp/language/user_literal


template <typename T>
void show (std::ostream& os, T const& t) {
	using namespace std;
	using cxxomfort::library::type_name;
	os<< "[type:"<< type_name<T>()<< " sizeof:"<< sizeof(T)<< " value:"<< t<< " ] "<< endl;
	
}

int main () {
	using namespace std;
	using namespace cxxomfort::literals;
	using namespace cxxomfort::library::literals;
	using cxxomfort::library::type_name;
	
	cout<< " 1, int     : "; show(cout, 4); // should be: int
	cout<< type_name<size_t>()<< endl;
	cout<< " 1, size_t  : "; show(cout, 2524 | zu); // should be: size_t
	cout<< type_name<unsigned short>()<< endl;
	cout<< " 1, u.short : "; show(cout, 2524 | hu); // should be: unsigned short
	cout<< type_name<uintmax_t>()<< endl;
	cout<< " 1, uintmax : "; show(cout, 2524 | ju); // should be: uintmax
	cout<< endl;
	
	show(cout, 400 | dbl); // should be: 800 

	// cool thing: they also work as normal functions (function objects)
	cout<< "\n 2 - Using as function objects: foo ( value ) "<< endl;
	cout<< "signed    : "; show(cout, hi(9)); // should be: unsigned short
	cout<< "unsigned  : "; show(cout, hu(-10)); // should be: unsigned short, but should throw a sign conversion warning
	
	cout<< endl;
	
	// and in C++11 onwards, as literal suffixes
#if (CXXOMFORT_CXX_STD >= 2011)
	cout<< "\n 3 - Using as C++11 suffixes: value_foo "<< endl;
    show(cout, 17417_hu); // should be: unsigned short
    show(cout, 17418_zu); // should be: size_t
    constexpr auto xi = 5000_hu;
    cout<< "type of xi: "<< type_name<decltype(xi)>()<< endl;
    
    
#endif


}
